package tp.pr3;

import java.util.Scanner;

import tp.pr3.instructions.Instruction;
import tp.pr3.instructions.exceptions.InstructionExecutionException;
import tp.pr3.instructions.exceptions.WrongInstructionFormatException;
import tp.pr3.items.Item;
import tp.pr3.items.ItemContainer;

/**
 * This class represents the robot engine. It controls robot movements by
 * processing the instructions introduced with the keyboard. The engine stops
 * when the robot arrives at the space ship, runs out of fuel or receives a quit
 * instruction.
 * 
 * The robot engine is also responsible for updating the fuel level and the
 * recycled material according to the actions that the robot performs in the
 * city.
 * 
 * The robot engine also contains an inventory where the robot stores the items
 * that it collects from the city
 */
public class RobotEngine {
	private NavigationModule nav;
	private ItemContainer items;
	private int recycledMaterial;
	private int fuel;
	private boolean endGame;

	private static final String LINE_SEPARATOR = System
			.getProperty("line.separator");

	/**
	 * Creates the robot engine in an initial place, facing an initial direction
	 * and with a city map. Initially the robot has not any items or recycled
	 * material but it has an initial amount of fuel (50)
	 * 
	 * @param cityMap
	 *            - The city where the robot wanders
	 * @param initialPlace
	 *            - - The place where the robot starts
	 * @param dir
	 *            - The initial direction where the robot is facing
	 */
	public RobotEngine(City cityMap, Place initialPlace, Direction dir) {
		nav = new NavigationModule(cityMap, initialPlace);
		nav.initHeading(dir);
		items = new ItemContainer();
		recycledMaterial = 0;
		fuel = 100;
		endGame = false;
	}

	/**
	 * Empieza el motor del robot
	 */
	public void startEngine() {
		Scanner sc = new Scanner(System.in);

		nav.scanCurrentPlace();
		System.out.println(Message.LOOKING.replace("<dir>", nav
				.getCurrentHeading().toString()));
		printRobotState();
		while (!endGame && !nav.atSpaceship() && fuel > 0) {
			System.out.print(Message.PROMPT);
			String line = sc.nextLine();
			try {
				Instruction ins = Interpreter.generateInstruction(line);
				ins.configureContext(this, nav, items);
				ins.execute();
			} catch (WrongInstructionFormatException e) {
				System.out.println(Message.NOT_UNDERSTAND);
			} catch (InstructionExecutionException e) {
				System.out.println(e.getMessage());
			}

		}
		if (fuel <= 0)
			System.out.println(Message.NO_FUEL);

		if (nav.atSpaceship())
			System.out.println(Message.AT_SPACESHIP);
		sc.close();

	}

	/**
	 * Prints the information about all possible instructions
	 */
	public void requestHelp() {
		System.out.println(Interpreter.interpreterHelp());
	}

	/**
	 * Requests the end of the simulation
	 */
	public void requestQuit() {
		endGame = true;
	}

	/**
	 * Prints the state of the robot
	 */
	public void printRobotState() {
		System.out.println(statusInfo());
	}

	/**
	 * Adds an amount of fuel to the robot (it can be negative)
	 * 
	 * @param fuel
	 *            - the amount of fuel
	 */
	public void addFuel(int fuel) {
		this.fuel += fuel;

		if (this.fuel < 0)
			this.fuel = 0;
	}

	/**
	 * Increases the amount of recycled material of the robot
	 * 
	 * @param weight
	 *            - Amount of recycled material
	 */
	public void addRecycledMaterial(int weight) {
		this.recycledMaterial += weight;
	}

	/**
	 * Returns the current fuel level of the robot. This method is mandatory FOR
	 * TESTING PURPOSES
	 */
	public int getFuel() {
		return this.fuel;
	}

	/**
	 * Returns the current weight of recycled material that the robot carries.
	 * This method is mandatory FOR TESTING PURPOSES
	 */
	public int getRecycledMaterial() {
		return this.recycledMaterial;
	}

	/**
	 * 
	 * @return a string containing relevant info to WALL�E's levels of power and
	 *         recycled material
	 */
	public java.lang.String statusInfo() {
		return "      * My power is " + this.fuel + LINE_SEPARATOR
				+ "      * My reclycled material is " + this.recycledMaterial;
	}

}
